<template>
  <el-card class="spu-top">
    <el-form
      label-width="100px"
      ref="SpuFormRef"
      :model="SpuFormDate"
      :rules="SpuRules"
    >
      <el-form-item label="SPU名称" prop="spuName">
        <el-input placeholder="SPU名称" v-model="SpuFormDate.spuName" />
      </el-form-item>

      <el-form-item label="品牌" prop="tmId">
        <el-select placeholder="请选择" v-model="SpuFormDate.tmId">
          <el-option
            v-for="tm in trademarkList"
            :key="tm.id"
            :label="tm.tmName"
            :value="tm.id"
          />
        </el-select>
      </el-form-item>

      <el-form-item label="品牌描述" prop="description">
        <el-input
          type="textarea"
          placeholder="SPU描述"
          :rows="4"
          v-model="SpuFormDate.description"
        />
      </el-form-item>

      <el-form-item label="SPU图片" prop="spuImageList">
        <el-upload
          v-model:file-list="SpuFormDate.spuImageList"
          :before-upload="beforeAvatarUpload"
          :action="UPLOAD_URL + '/admin/product/fileUpload'"
          list-type="picture-card"
          :on-preview="handlePictureCardPreview"
          :on-success="handleAvatarSuccess"
          :limit="MAX_LIMIT_NUM"
        >
          <el-icon><Plus /></el-icon>
          <template #tip>
            <div class="el-upload__tip">
              只能上传jpg/png/gif文件，且不超过200kb
            </div>
          </template>
        </el-upload>
        <el-dialog v-model="dialogVisible" width="30%">
          <img
            class="sup-img"
            w-full
            :src="dialogImageUrl"
            alt="Preview Image"
          />
        </el-dialog>
      </el-form-item>

      <el-form-item label="销售属性" prop="spuSaleAttrList">
        <el-select
          :placeholder="`还剩 ${fillBaseSaleAttrList.length} 未选择`"
          class="spu-bottom"
          v-model="spuSaleAttrItem"
        >
          <el-option
            v-for="sale in fillBaseSaleAttrList"
            :key="sale.id"
            :label="sale.name"
            :value="sale.id + ':' + sale.name"
          />
        </el-select>
        <el-button
          type="primary"
          :icon="Plus"
          class="spu-attr"
          :disabled="!spuSaleAttrItem"
          @click="addSaleAttrItem"
          >添加销售属性</el-button
        >
        <el-table :data="SpuFormDate.spuSaleAttrList" border class="spu-top">
          <el-table-column
            type="index"
            label="序号"
            width="60"
            align="center"
          />
          <el-table-column prop="saleAttrName" label="属性名" width="120" />
          <el-table-column label="属性值列表">
            <template v-slot="{ row }">
              <el-tag
                closable
                type="success"
                class="spu-tag"
                v-for="(saleAttrVal, index) in row.spuSaleAttrValueList"
                :key="saleAttrVal.saleAttrValueName"
                @close="delSaleAttrVal(row, index)"
              >
                {{ saleAttrVal.saleAttrValueName }}
              </el-tag>
              <el-input
                v-model="saleAttrValueName"
                placeholder="名称"
                ref="inputRef"
                class="spu-btn"
                v-if="row.isEdit"
                @blur="addSaleAttrVal(row)"
                @keyup.enter="addSaleAttrVal(row)"
              ></el-input>
              <el-button
                size="small"
                :icon="Plus"
                v-else
                @click="showEdit(row)"
              ></el-button>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="120">
            <template v-slot="{ $index }">
              <el-tooltip content="删除" placement="bottom-end" effect="light">
                <el-button
                  type="danger"
                  size="small"
                  :icon="Delete"
                  @click="delSaleAttrItem($index)"
                ></el-button>
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="submitFormDate">保存</el-button>
        <el-button @click="ShowSpuList">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script lang="ts">
export default {
  name: "AddSetSpuItem",
};
</script>

<script lang="ts" setup>
import { onMounted, ref, reactive, computed, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { Delete, Plus } from "@element-plus/icons-vue";

import type { UploadProps, FormInstance, FormRules } from "element-plus";
import type { TrademarkList } from "@/api/product/models/trademarkModel";
import type {
  BaseSaleAttrList,
  SpuSaleAttrItem,
  AddSetSpuListItem,
} from "@/api/product/models/spuModel";
import { getTrademarkListApi } from "@/api/product/trademark";
import {
  baseSaleAttrListApi,
  addSpuApi,
  getSpuImageListApi,
  getSpuSaleAttrListApi,
  setSpuApi,
} from "@/api/product/spu";
import { useCategoryStore } from "@/stores/category";
const CategoryStore = useCategoryStore();

//定义品牌列表
const trademarkList = ref<TrademarkList>([]);
//定义销售属性列表
const baseSaleAttrList = ref<BaseSaleAttrList>([]);

//发请求
//品牌数据
onMounted(async () => {
  trademarkList.value = await getTrademarkListApi();
});
//销售属性数据
onMounted(async () => {
  baseSaleAttrList.value = await baseSaleAttrListApi();
});

//取消按钮的回调
//接收自定义事件
const emits = defineEmits(["isShowAddSpu"]);
const ShowSpuList = () => {
  emits("isShowAddSpu", 1);
};

//接受props数据
const props = defineProps<{
  spu: AddSetSpuListItem; // 是ts类型，小写
}>();

/***************************表单校验功能*********************************************/
//获取el-form组件的实例对象 可以使用.validate(使整个表单触发表单校验) .resetFields(清空表单) .clearValidate(清空表单校验结果)
const SpuFormRef = ref<FormInstance>();

//表单数据
//尽量和提交表单请求数据名称一样
// const SpuFormDate = reactive<AddSetSpuItem>({
//   // category3Id: 0,
//   description: "",
//   // id: 0,
//   spuImageList: [],
//   spuName: "",
//   spuSaleAttrList: [],
//   tmId: undefined,
// });
const SpuFormDate = reactive<AddSetSpuListItem>(props.spu);

//自定义校验规则
const saleAttrListValidator = (rule: any, value: any, callback: any) => {
  // value 表单的那个数据
  if (value.length == 0) {
    callback(new Error("请至少添加一个销售属性"));
  } else if (
    value.some(
      (saleAttr: SpuSaleAttrItem) => !saleAttr.spuSaleAttrValueList.length
    )
  ) {
    callback(new Error("每个销售属性都必须添加一个销售属性值"));
  } else {
    callback();
  }
};

//表单校验规则
const SpuRules = reactive<FormRules>({
  spuName: [
    { required: true, message: "请输入SPU名称", trigger: "blur" },
    { min: 1, max: 5, message: "请输入1-5个字符之间", trigger: "blur" },
  ],
  tmId: [{ required: true, message: "请选择你的品牌" }],
  description: [{ required: true, message: "请输入SPU描述", trigger: "blur" }],
  spuImageList: [{ required: true, message: "请至少上传一张图片" }],
  spuSaleAttrList: [
    {
      required: true,
      //自定义校验规则
      validator: saleAttrListValidator,
    },
  ],
});

/***************************上传图片功能*********************************************/
//图片上传路径
const UPLOAD_URL = import.meta.env.VITE_API_URL;
//限制上传图片数量
const MAX_LIMIT_NUM = 10;
// 隐藏上传框
const isShowImgBtn = computed(() => {
  return SpuFormDate.spuImageList.length < MAX_LIMIT_NUM
    ? "inline-flex"
    : "none";
});

const dialogImageUrl = ref("");
const dialogVisible = ref(false);

//放大的回调
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url as string;
  dialogVisible.value = true;
};

//上传成功的回调
const handleAvatarSuccess: UploadProps["onSuccess"] = () => {
  //提示限制图片
  if (SpuFormDate.spuImageList.length == MAX_LIMIT_NUM) {
    ElMessage.warning(`最多只能上传${MAX_LIMIT_NUM}张照片`);
  }
  if (SpuFormDate.spuImageList.length == 1) {
    //因为点击添加触发了表单校验，上传成功后，无法清空表单校验错误信息，所以需要这里清理
    SpuFormRef.value?.clearValidate(["spuImageList"]);
  }
};

// 上传前的回调
//定义合法的图片类型数组
const imageType = ["image/jpg", "image/jpeg", "image/png", "image/gif"];
const beforeAvatarUpload: UploadProps["beforeUpload"] = (rawFile) => {
  if (!imageType.includes(rawFile.type)) {
    ElMessage.error("上传的图片必须是jpg或者png或者gif格式");
    return false;
  } else if (rawFile.size / 1024 > 200) {
    ElMessage.error("上传的图片不能超过200kb");
    return false;
  }
  return true;
};

/******************************添加/删除销售属性功能*********************************/
//收集销售属性
const spuSaleAttrItem = ref("");
//添加销售属性
const addSaleAttrItem = () => {
  //解构数组
  const [baseSaleAttrId, saleAttrName] = spuSaleAttrItem.value.split(":");
  SpuFormDate.spuSaleAttrList.push({
    baseSaleAttrId: +baseSaleAttrId,
    saleAttrName,
    spuSaleAttrValueList: [],
    //标识符
    isEdit: false,
  });
  //清空下拉框
  spuSaleAttrItem.value = "";
};
//删除销售属性
const delSaleAttrItem = (index: number) => {
  SpuFormDate.spuSaleAttrList.splice(index, 1);
};

//添加或者删除属性要更改销售属性列表删除（下拉框）
const fillBaseSaleAttrList = computed(() => {
  return baseSaleAttrList.value.filter((baseSaleAttr) => {
    //有相等的就不用返回，所以取反
    return !SpuFormDate.spuSaleAttrList.some(
      (spuSaleAttr) => spuSaleAttr.baseSaleAttrId == baseSaleAttr.id
    );
  });
});

/***********************添加/删除销售属性值功能****************************************/
//输入框的实例
const inputRef = ref();

//input框数据
const saleAttrValueName = ref("");

//添加属性值,显示编辑模式
const showEdit = async (row: SpuSaleAttrItem) => {
  row.isEdit = true;
  //等待DOM更新
  await nextTick();
  //输入框聚集
  inputRef.value.focus();
};

//失去焦点或者按回车，显示文本模式
const addSaleAttrVal = (row: SpuSaleAttrItem) => {
  if (saleAttrValueName.value) {
    row.spuSaleAttrValueList.push({
      baseSaleAttrId: row.baseSaleAttrId,
      saleAttrValueName: saleAttrValueName.value,
    });
    //清空输入框数据
    saleAttrValueName.value = "";
  }

  //显示文本模式
  row.isEdit = false;
};

//属性值标签点击叉号删除
const delSaleAttrVal = (row: SpuSaleAttrItem, index: number) => {
  row.spuSaleAttrValueList.splice(index, 1);
};

/***************************提交表单功能*********************************************/
const submitFormDate = () => {
  const data = {
    ...SpuFormDate,
    spuImageList: SpuFormDate.spuImageList.map((img) => {
      return {
        imgName: img.name,
        imgUrl: img.response ? (img.response as any).data : img.url,
      };
    }),
    category3Id: CategoryStore.category3Id,
  };
  //触发全部表单校验
  SpuFormRef.value?.validate(async (valid) => {
    //valid为true表示校验通过,发请求
    if (valid) {
      if (SpuFormDate.id) {
        await setSpuApi(data);
      } else {
        //发请求
        await addSpuApi(data);
      }
      ElMessage.success(`${SpuFormDate.id ? "修改" : "添加"}SPU成功`);

      //跳转到SPU列表页
      ShowSpuList();
    }
  });
};

/***************************修改spu功能功能*********************************************/
//渲染图片
onMounted(async () => {
  //如果SpuFormDate有id代表修改SPU，如果没有代表添加SPU
  const { id } = SpuFormDate;
  if (!id) return;
  const res = await getSpuImageListApi(id);
  SpuFormDate.spuImageList = res.map((item) => {
    return {
      name: item.imgName,
      url: item.imgUrl,
    };
  });
});

//渲染销售属性
onMounted(async () => {
  const { id } = SpuFormDate;
  if (!id) return;
  SpuFormDate.spuSaleAttrList = await getSpuSaleAttrListApi(id);
});
</script>

<style scoped>
.spu-attr {
  margin-left: 10px;
}
.spu-top {
  margin-top: 20px;
}
.sup-img {
  width: 100%;
  height: 100%;
}
.spu-top :deep(.el-upload--picture-card) {
  display: v-bind(isShowImgBtn);
}
.spu-btn {
  width: 200px;
  height: 24px;
}
.spu-tag {
  margin-right: 5px;
}
</style>
